﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Web.Http.ModelBinding.Binders;
using Core.Models;
using Service.AI;
using Service.Helpers;
using Service.Workflow.Opening.Query;
using ShortBus;

namespace Service.Workflow.Game.Command
{
    public class MoveGameCommandHandler : IAsyncQueryHandler<MoveGameCommand, MoveGameCommandResponse>
    {
        private readonly IMediator mediator;
        public MoveGameCommandHandler(IMediator mediator)
        {
            this.mediator = mediator;
        }

        public async Task<MoveGameCommandResponse> HandleAsync(MoveGameCommand command)
        {
            GameState gs = CurrentGameHelper.Instance.GetCurrentGameState(command.GameId);

            if (command.FullMove != null)
            {
                MoveContent mc = new MoveContent(command.FullMove);
                gs.MovePiece(mc.MovingPiecePrimary.SrcPosition, mc.MovingPiecePrimary.DstPosition);
            }
            else if(command.MoveSource != null && command.MoveTarget != null)
            {
                gs.MovePiece((byte)CurrentGameHelper.Instance.GetPositionCol(command.MoveSource), (byte)CurrentGameHelper.Instance.GetPositionRow(command.MoveSource),
               (byte)CurrentGameHelper.Instance.GetPositionCol(command.MoveTarget), (byte)CurrentGameHelper.Instance.GetPositionRow(command.MoveTarget));
            }

            var openingQueryResponse = await mediator.RequestAsync(new OpeningQuery
            {
                FEN = gs.GetBoardFen(true)
            });

            if (openingQueryResponse.Data.OpeningFound)
            {
                var randomOpening = openingQueryResponse.Data.Moves.OrderBy(x => Guid.NewGuid()).First();

                //doing the move for in the gameState
                var moveContent = new MoveContent(randomOpening);
                gs.MovePiece(moveContent.MovingPiecePrimary.SrcPosition, moveContent.MovingPiecePrimary.DstPosition);

                return new MoveGameCommandResponse()
                {
                    FullMove = randomOpening
                };
            }




            //***********************************************************
            AlphaBeta ab = new AlphaBeta(gs);
            MovesInfo bestMove = ab.StartIteration(3, true);
            //***********************************************************




            List<MovesInfo> lstPossibleMoves = gs.GetBoardMoves();
            Random rnd = new Random();
            int randomIndex = rnd.Next(lstPossibleMoves.Count - 1);

            //make the move the Ai chose on the current gamestate then return said move to the UI
            MoveContent mcAi = new MoveContent();
            if (bestMove != null)
            {
                mcAi = new MoveContent(bestMove.WriteFullMove());
            }
            else
            {
                bestMove = lstPossibleMoves[randomIndex];
                mcAi = new MoveContent(lstPossibleMoves[randomIndex].WriteFullMove());
            }
            
            gs.MovePiece(mcAi.MovingPiecePrimary.SrcPosition, mcAi.MovingPiecePrimary.DstPosition);
            return new MoveGameCommandResponse(){
                MoveSource = bestMove.WriteSourcePos(),
                MoveTarget = bestMove.WriteDestPos()
            };
            
        }
    }
}